上一篇學會了如何發起交易,這一篇將會進入到另一個重要功能,就是部署合約!
應該有人看到標題就想問:為什麼已經用了專用函式庫 web3.js ,還要在前端使用 Truffle 呢?難道 web3.js 不能部署合約嗎?其實 web3.js 可以部署合約的,但是當合約需要與函式庫做連結時就會十分麻煩,幸好 Truffle 有提供相關的方法讓我們能夠輕鬆把函式庫與合約接在一起,可喜可賀~![]()
我們其實只需要使用 Truffle 的部分功能,所以安裝要的功能即可,方法很簡單,在專案中使用 npm 安裝@truffle/contract:
npm install @truffle/contract
然後我們在 ProviderService 中使用:
declare let require: any;
const TruffleContract = require('@truffle/contract');
這樣前置作業就完成了!
我們接下來會用之前設計的 Resume.sol 與 StrLib.sol 來示範部署合約及函式庫。先將智能合約進行編譯:
truffle compile
部署智能合約需要用到 ABI 與 bytecode ,而這些資訊放在 Resume.json 與 StrLib.json 中,所以我們要將這兩個檔案引入。先在 types 資料夾中新增 contract.ts ,並從 index.ts 中 export :
export * from './contract';
接著在 contract.ts 中使用 require 來引入 Resume.json 與 StrLib.json :
declare let require: any;
export const ResumeContract = require('../../../truffle/build/contracts/Resume.json');
export const StrLibContract = require('../../../truffle/build/contracts/StrLib.json');
如此一來,就可以從 ResumeContract 與 StrLibContract 中取得 ABI 與 bytecode 囉!
Resume 合約在部署時需要帶上 name 、 address 、 age 與 gender 資訊,所以我們來定義資料格式,就放在 contract.ts 中:
export interface ResumeInitialOptions {
name: string;
address: string;
age: number;
gender: number;
}
好了之後開始定義我們部署合約的方法。一開始要先將編譯的合約帶入 TruffleContract 中,並且要設定 Provider ,理所當然地使用 this.web3.currentProvider ,這邊需要特別去指定 Resume 合約使用的 networkId ,否則會報錯,然後透過 new 進行部署,需要先將 StrLib 部署,再將 StrLib 的合約位址與 Resume 透過 link(name, address) 做連結,然後才部署 Resume 合約:
public deployResume(info: ResumeInitialOptions): Observable<any> {
const strLib = TruffleContract(StrLibContract);
const resume = TruffleContract(ResumeContract);
strLib.setProvider(this.web3.currentProvider);
resume.setProvider(this.web3.currentProvider);
resume.setNetwork(this.web3.currentProvider.networkVersion);
return from(strLib.new({ from: this.defaultAccount })).pipe(
mergeMap((instance: any) => {
resume.link('StrLib', instance.address);
return resume.new(info.name, info.address, info.age, info.gender, { from: this.defaultAccount });
}),
take(1)
);
}
這個設計方法是展示如何部署函式庫與合約,並且連結剛部署上去的 library 合約,真實應用場景可以先用 truffle migrate 把 StrLib 部署上去,再把 address 記起來填入
link(name, address)中即可。
老樣子在 app.component.ts 中做測試:
constructor(private provider: ProviderService) {
const info = {
name: 'HAO',
address: '0x579c43911C862E16fEB199233ec2d32e441b7713',
age: 21,
gender: 0
} as ResumeInitialOptions;
this.provider.getAccount().pipe(
take(1),
mergeMap(accounts => {
this.provider.defaultAccount = accounts[0];
return this.provider.deployResume(info);
})
).subscribe(instance => {
console.log(instance);
});
}
這時候打開網頁會跳出 MetaMask ,第一個是 StrLib 的交易請求:
按下確定後會跳出 Resume 的交易請求:
都完成後到 Ganache 中查看交易內容:
這樣就成功部署啦~~
借助 web3.js 來取得 Provider ,然後透過 Truffle 部署合約,並且能夠與 library 做連結,這部分算是 DApp 的核心功能之一,務必熟悉!